package com.pudu.mydemo.fragment;

import android.animation.ObjectAnimator;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.github.pwittchen.networkevents.library.BusWrapper;
import com.github.pwittchen.networkevents.library.ConnectivityStatus;
import com.github.pwittchen.networkevents.library.NetworkEvents;
import com.github.pwittchen.networkevents.library.event.ConnectivityChanged;
import com.pudu.mydemo.act.BaseHomeActivity;
import com.pudu.mydemo.act.HomeActivity;
import com.pudu.mydemo.entity.AccessPoint;
import com.pudu.mydemo.utils.WiFi;
import com.pudutech.pdrobot.R;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import com.wang.avi.AVLoadingIndicatorView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * Created by guiliu on 2016/7/16.
 */
public class WifiFragment extends Fragment implements WifiLoginBlurDialogFragment.LoginInputListener{
    private String Tag = this.getClass().getSimpleName();
    private BusWrapper busWrapper;
    private NetworkEvents networkEvents;
    private WifiManager mWifiManager;
    private List<ScanResult> mScanResults;
    private List<AccessPoint> accessPoints;
    private ListView wifiListView;
//    private ProgressBar searchwifi_bar ;
    private ImageButton cancel , back, wifi_refresh;
    private IntentFilter mFilter;
    private WifiAdapter wifiAdapter;
    private AtomicBoolean mConnected = new AtomicBoolean(false);
    private NetworkInfo.DetailedState mLastState = null;
    private WifiInfo mLastInfo = null;
    private AccessPoint itemclickaccessPoint = null;
    private WifiConfiguration itemclickConfig = null;
//    private ProgressDialog mDialog;
    private boolean comefromWelcome;
    private AVLoadingIndicatorView avi;
    private ObjectAnimator objectAnimator;
    private boolean fromUser;
    /** These values are matched in string arrays -- changes must be kept in sync */
    static final int SECURITY_NONE = 0;
    private boolean login;
//    static final int SECURITY_WEP = 1;
//    static final int SECURITY_PSK = 2;
//    static final int SECURITY_EAP = 3;
    private static final int[] STATE_SECURED = {
            R.attr.state_encrypted
    };
    private static final int[] STATE_NONE = {};
    private Scanner mScanner;
    // Combo scans can take 5-6s to complete - set to 10s.
    private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;

    @Override
    public void onResume() {
        super.onResume();
        busWrapper.register(this);
        networkEvents.register();
        mFilter = new IntentFilter();
         mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
//        mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
//        mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
         getActivity().registerReceiver(mReceiver, mFilter);
//         mWifiManager.startScan();
        if( !WiFi.isWifiOpen()) {
            openWifi();
        }
         mScanner.forceScan();
        if(comefromWelcome) {
            cancel.setVisibility(View.VISIBLE);
            back.setVisibility(View.GONE);
        }else {
            cancel.setVisibility(View.GONE);
            back.setVisibility(View.VISIBLE);
        }
//         searchwifi_bar.setVisibility(View.GONE);
        objectAnimator.start();

    }

    @Override
    public void onPause() {
        super.onPause();
        busWrapper.unregister(this);
        networkEvents.unregister();
        mScanner.pause();
        objectAnimator.cancel();
        getActivity().unregisterReceiver(mReceiver);
    }



    private BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
//                Log.e(Tag,"SCAN_RESULTS_AVAILABLE_ACTION");
                objectAnimator.cancel();
//                objectAnimator.end();
                accessPoints.clear();
                accessPoints = constructAccessPoints();
                wifiAdapter.notifyDataSetChanged();
//                mWifiManager.startScan();
            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
                NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
                        WifiManager.EXTRA_NETWORK_INFO);
                Log.e(Tag,"info connectd:"+info.isConnected());
                mConnected.set(info.isConnected());
                if(mConnected.get() && comefromWelcome) {
                    Log.e(Tag,"comefromWelcome to home");
                    comefromWelcome = false;
//                    launchActivity();
                } else{
                    updateConnectionState(info.getDetailedState());
                }

            }
        }
    };

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.layout_wifi, null);
        initView(v);

        mWifiManager = (WifiManager)getActivity().getSystemService(Context.WIFI_SERVICE);
        mScanResults = new ArrayList<>();
        accessPoints = new ArrayList<>();
        wifiAdapter = new WifiAdapter();
        wifiListView.setAdapter(wifiAdapter);
        wifiListView.setOnItemClickListener(mItemOnClick);
//        mDialog = new ProgressDialog(this);
        mScanner = new Scanner();
        busWrapper = getOttoBusWrapper(new Bus());
        networkEvents = new NetworkEvents(getActivity(), busWrapper).enableInternetCheck()
                .enableWifiScan();
        Bundle data = getArguments();
       /* if("android.intent.action.welcome".equals(getIntent().getAction())){
            comefromWelcome = true;
            Log.e(Tag,"comefromWelcome");
        } else if("android.intent.action.setting".equals(getIntent().getAction())) {
            comefromWelcome = false;
            Log.e(Tag,"comefromSetting");
        }*/
        comefromWelcome = true;
        return v;
    }



    public void initView(View v) {
        wifiListView = (ListView)v.findViewById(R.id.wifiListView);
//        searchwifi_bar = (ProgressBar)findViewById(R.id.searchwifi_bar);
        cancel = (ImageButton)v.findViewById(R.id.cancel);
        back = (ImageButton)v.findViewById(R.id.back);
        avi = (AVLoadingIndicatorView)v.findViewById(R.id.avi);
        wifi_refresh = (ImageButton)v.findViewById(R.id.wifi_refresh);
        wifi_refresh.setOnClickListener(mOnClick);
        back.setVisibility(View.GONE);

        objectAnimator = ObjectAnimator.ofFloat(wifi_refresh,"rotation",0f,360f);
        objectAnimator.setRepeatMode(ObjectAnimator.INFINITE);
        objectAnimator.setInterpolator(new LinearInterpolator());
        objectAnimator.setRepeatCount(-1);
        objectAnimator.setDuration(1000);
        back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                WifiFragment.this.finish();
            }
        });
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                Intent intent = new Intent(WifiFragment.this, HomeActivity.class);
//                startActivity(intent);
//                WifiFragment.this.finish();
            }
        });
    }


    private View.OnClickListener mOnClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //旋转刷新键
            objectAnimator.start();
            mScanner.resume();
        }
    };


    private OnItemClickListener mItemOnClick = new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                                long id) {
            if(wifiAdapter!=null) {
                 itemclickaccessPoint = (AccessPoint) wifiAdapter.getItem(position);
            }

           /* Radius : 8   12   20
            Down Scale Factor : 8.0    6.0   4.0
            Blurred achieved in : 18 ms   31ms  75ms
            Allocation : 4320ko (screen capture) + 270/360/540ko (FastBlur)*/
            WifiLoginBlurDialogFragment editNameDialog
                    = WifiLoginBlurDialogFragment.newInstance(
                   8,
                    8.0f,
                    false,
                   false,
                    itemclickaccessPoint.getSsid() != null ? itemclickaccessPoint.getSsid() : "",
                    itemclickaccessPoint.getmConfig() != null
            );
            itemclickConfig = itemclickaccessPoint.getmConfig();
            editNameDialog.show(getActivity().getFragmentManager(), "EditNameDialog");
        }

    };


    private void updateConnectionState(NetworkInfo.DetailedState state) {

        //ou my god, getssid = "\"" + unicode + "\""
        mLastInfo = mWifiManager.getConnectionInfo();
//        Log.e(Tag,"mLastInfo ssid: "+mLastInfo.getSSID()+" netID:" +mLastInfo.getNetworkId()+" state:"+state);
        if (state != null) {
            mLastState = state;
        }
        //将正在进行连接的networkId和所有accessPoint比较，更新对应accessPoint在listview连接状态
        for (AccessPoint accessPoint:
             accessPoints) {
            accessPoint.update(mLastInfo, state);
        }
        //多次接收到广播，滑动listview的同时重新绘制导致许多重复项？
        wifiAdapter.notifyDataSetChanged();
    }

    void startAnim(){
        avi.show();
        // or avi.smoothToShow();
    }

    void stopAnim(){
        avi.hide();
        // or avi.smoothToHide();
    }

    private Handler handler = new Handler();

    //这里回调意味着用户已经输入密码
    @Override
    public void onLoginInputComplete(String ssid, String password) {
        fromUser = true;
        if(itemclickConfig == null) {
          WiFi.connectToNewNetwork(mWifiManager,itemclickaccessPoint.getScanResult(),password);
        } else {
            WiFi.changePasswordAndConnect(mWifiManager,itemclickConfig,password);
        }
        startAnim();
        //当前属于断开状态，若密码错误则不会回调onEvent,只能延时
        if(!mConnected.get()) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if( !mConnected.get() ) {
                        //连接超时
                        stopAnim();
                        Toast.makeText(getActivity(),"连接超时",Toast.LENGTH_LONG).show();
                    }
                }
            },6000);
        }
        //由于connectToNewNetwork、changePasswordAndConnect返回true并不能表示连接成功，所以需要启动延时线程，判断登录是否成功。
//        TimeAsyncTask timeAsyncTask = new TimeAsyncTask();
//        timeAsyncTask.execute();
    }
    private class TimeAsyncTask extends AsyncTask<Void,Void,Void>{
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
//            mDialog.setMessage("正在登录中...");
//            mDialog.show();

            startAnim();
        }

        @Override
        protected Void doInBackground(Void... params) {
            int i = 0;
            //这里存在一个bug，当现在处于连接状态时，若用户重新输入密码登录，由于mConnected并还没有改变，所以会立即返回
            while (!mConnected.get() &&i < 15 ) {
                i++;
                Log.e(Tag,"登录状态mConnected:"+mConnected.get()+":I:"+i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
//            mDialog.dismiss();
            if(mConnected.get()){
                Toast.makeText(getActivity(),"登录成功",Toast.LENGTH_LONG).show();
//                mDialog.setMessage("登录成功...");
//                mDialog.dismiss();

                launchActivity();
            } else {
//                mDialog.setMessage("登录失败...");
                Toast.makeText(getActivity(),"登录失败",Toast.LENGTH_LONG).show();
            }
//            mDialog.dismiss();
            stopAnim();
        }
    }

    public void launchActivity() {
        Intent intent = new Intent(getActivity(),HomeActivity.class);
        startActivity(intent);
//        WifiFragment.this.finish();
    }
    private class Scanner extends Handler {
        private int mRetry = 0;

        void resume() {
            if (!hasMessages(0)) {
                sendEmptyMessage(0);
            }
        }

        void forceScan() {
            removeMessages(0);
            sendEmptyMessage(0);
        }

        void pause() {
            mRetry = 0;
            removeMessages(0);
        }

        @Override
        public void handleMessage(Message message) {

            if (mWifiManager.startScan()) {
                mRetry = 0;
            } else if (++mRetry >= 3) {
                mRetry = 0;
                return;
            }
            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
        }
    }
    class WifiAdapter extends BaseAdapter {


        @Override
        public int getCount() {
            return accessPoints.size();
        }

        @Override
        public Object getItem(int position) {
            return accessPoints.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;
            if( null == convertView) {
                viewHolder = new ViewHolder();
                convertView = View.inflate(getActivity(), R.layout.layout_wifi_item,null);
                viewHolder.signal = (ImageView) convertView.findViewById(R.id.signal);
                viewHolder.wifiname = (TextView)convertView.findViewById(R.id.wifiname);
                viewHolder.wificonnect = (TextView)convertView.findViewById(R.id.wifi_connect);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            AccessPoint accessPoint = accessPoints.get(position);
            String mRssi = accessPoint.getSsid();
            onBindView(viewHolder,accessPoint);
            viewHolder.wifiname.setText(mRssi);
            viewHolder.wificonnect.setText(refresh(accessPoint));
            return convertView;
        }


        class ViewHolder {
            TextView wifiname,wificonnect;
            ImageView signal;
        }


        private String refresh(AccessPoint accessPoint) {
            if (accessPoint.getState() != null && mConnected.get()) { // This is the active connection
                return  "已经连接";
            } else if (accessPoint.getmConfig() != null && accessPoint.getmConfig().status == WifiConfiguration.Status.DISABLED) {

                return "正在连接";
            } else if(accessPoint.getmRssi() == Integer.MAX_VALUE){
                return "不在范围内";
            } else {
                return "";
            }
        }

        protected void onBindView(ViewHolder viewHolder,AccessPoint accessPoint) {
            ImageView signal = /*(ImageView) view.findViewById(R.id.signal)*/viewHolder.signal;
            if (accessPoint.getmRssi() == Integer.MAX_VALUE) {
                signal.setImageDrawable(null);
            } else {
                signal.setImageLevel(accessPoint.getLevel());
                signal.setImageResource(R.drawable.wifi_signal);
                signal.setImageState((accessPoint.getSecurity() != SECURITY_NONE) ?
                        STATE_SECURED : STATE_NONE, true);
            }
        }
    }




    /** Returns sorted list of access points */
    private List<AccessPoint> constructAccessPoints() {
       accessPoints = new ArrayList<AccessPoint>();
        /** Lookup table to more quickly update AccessPoints by only considering objects with the
         * correct SSID.  Maps SSID -> List of AccessPoints with the given SSID.  */
        Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();

        final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
        if (configs != null) {
            for (WifiConfiguration config : configs) {
                AccessPoint accessPoint = new AccessPoint(config);
                accessPoint.update(mLastInfo, mLastState);
                accessPoints.add(accessPoint);
                apMap.put(accessPoint.getSsid(), accessPoint);
            }
        }

        final List<ScanResult> results = mWifiManager.getScanResults();
        if (results != null) {
            for (ScanResult result : results) {
                // Ignore hidden and ad-hoc networks.
                if (result.SSID == null || result.SSID.length() == 0 ||
                        result.capabilities.contains("[IBSS]")) {
                    continue;
                }

                boolean found = false;
                for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
                    if (accessPoint.update(result))
                        found = true;
                }
                if (!found) {
                    AccessPoint accessPoint = new AccessPoint(result);
                    accessPoints.add(accessPoint);
                    apMap.put(accessPoint.getSsid(), accessPoint);
                }
            }
        }

        // Pre-sort accessPoints to speed preference insertion
        Collections.sort(accessPoints);
      /*  //remove the out of range wifi
        Iterator<AccessPoint> it = accessPoints.iterator();
        while(it.hasNext()) {
            AccessPoint accessPoint = it.next();
            if(accessPoint.getmRssi() == Integer.MAX_VALUE) {
                it.remove();
            }
        }*/
        return accessPoints;
    }

    /** A restricted multimap for use in constructAccessPoints */
    private class Multimap<K,V> {
        private HashMap<K,List<V>> store = new HashMap<K,List<V>>();
        /** retrieve a non-null list of values with key K */
        List<V> getAll(K key) {
            List<V> values = store.get(key);
            return values != null ? values : Collections.<V>emptyList();
        }

        void put(K key, V val) {
            List<V> curVals = store.get(key);
            if (curVals == null) {
                curVals = new ArrayList<V>(3);
                store.put(key, curVals);
            }
            curVals.add(val);
        }
    }

    //只有连接状态发生变化时才会调用，存在一种情况offline -> offline不会调用，即在没有登录的情况下输入错误的密码
    @Subscribe
    @SuppressWarnings("unused") public void onEvent(ConnectivityChanged event) {
        handler.removeCallbacksAndMessages(null);
        Log.e("connectcheck","begin");
        if( event.getConnectivityStatus().equals(ConnectivityStatus.OFFLINE) ){
            Log.e("connectcheck","offline");
            if(fromUser)  Toast.makeText(getActivity(), "密码错误", Toast.LENGTH_SHORT).show();
        } else if(event.getConnectivityStatus().equals(ConnectivityStatus.WIFI_CONNECTED)){
            Log.e("connectcheck","connected");
        } else if(event.getConnectivityStatus().equals(ConnectivityStatus.WIFI_CONNECTED_HAS_NO_INTERNET)) {
            Log.e("connectcheck","connected no internet");
            if(fromUser) {
                Toast.makeText(getActivity(), "连接WiFi成功", Toast.LENGTH_SHORT).show();
//                launchActivity();
            }
        }
        stopAnim();

    }

    private BusWrapper getOttoBusWrapper(final Bus bus) {
        return new BusWrapper() {
            @Override public void register(Object object) {
                bus.register(object);
            }

            @Override public void unregister(Object object) {
                bus.unregister(object);
            }

            @Override public void post(Object event) {
                bus.post(event);
            }
        };
    }

    /**
     *  打开WIFI
     */
    private void openWifi() {
        if (!mWifiManager.isWifiEnabled()) {
            mWifiManager.setWifiEnabled(true);
        }

    }
}
